// Lab001.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include "dependencies.h"
#include "FileOps.h"
#include "Generators.h"
#include "Chypering.h"

void ExecGenerateKey(std::string filename);
void ExecEncodeCBC(std::string keyFileName, std::string inFileName, std::string outFileName);
void ExecDecodeCBC(std::string keyFileName, std::string inFileName, std::string outFileName);
void ExecEncodeOFB(std::string keyFileName, std::string inFileName, std::string outFileName);
void ExecDecodeOFB(std::string keyFileName, std::string inFileName, std::string outFileName);
void Usage(char* prog);

int main(int argc, char* argv[])
{
	if(argc == 0)
	{
		Usage(argv[0]);
		return -1;
	};

	if(strcmp(argv[1], "/key") == 0)
	{
		printf("Key generation in progress...");
		ExecGenerateKey(argv[2]);
	}
	else if(strcmp(argv[1], "/ofb_enc") == 0)
	{
		printf("OFB mode. Encryption in progress...");
		ExecEncodeOFB(argv[2], argv[3], argv[4]);
	}
	else if(strcmp(argv[1], "/ofb_dec") == 0)
	{
		printf("OFB mode. Decryption in progress...");
		ExecDecodeOFB(argv[2], argv[3], argv[4]);
	}
	else if(strcmp(argv[1], "/cbc_enc") == 0)
	{
		printf("CBC mode. Encryption in progress...");
		ExecEncodeCBC(argv[2], argv[3], argv[4]);
	}
	else if(strcmp(argv[1], "/cbc_dec") == 0)
	{
		printf("CBC mode. Decryption in progress...");
		ExecDecodeCBC(argv[2], argv[3], argv[4]);
	}
	else
	{
		Usage(argv[0]);
	};

	printf("\nDone!");
	return 0;
}

void Usage(char* prog)
{
	printf("USAGE:\n");
	printf("\t%s /key <keyfile> - Generates a key\n",prog);
	printf("\t%s /cbc_enc <keyfile> <infile> <outfile> - Encrypt file with CBC\n",prog);
	printf("\t%s /cbc_dec <keyfile> <infile> <outfile> - Decrypt file with CBC\n",prog);
	printf("\t%s /ofb_enc <keyfile> <infile> <outfile> - Encrypt file with OFB\n",prog);
	printf("\t%s /ofb_dec <keyfile> <infile> <outfile> - Decrypt file with OFB\n",prog);
	printf("\n");
};

void ExecGenerateKey(std::string filename)
{
	AC::HexParser Ox;
	AC::Block<BLOCK_LEN> genBlock;
	std::ofstream file(filename.c_str(), std::ios::binary | std::ios::out);

	if(file.is_open())
	{
		genBlock = GenerateKey();

		file.write(Ox(genBlock.Get()).c_str(), genBlock.Size() * 2);
		file.close();
	};
};

void ExecEncodeCBC(std::string keyFileName, std::string inFileName, std::string outFileName)
{
	AC::AES::Key<KEY_LEN> key = ReadKeyFile(keyFileName);
	AC::AES::IV iv;
	AC::BlockData<BLOCK_LEN> input;
	AC::BlockData<BLOCK_LEN> output;

	input = ReadBinaryFile(inFileName);

	output = EncodeCBC(key, iv, input);
	WriteBinaryFile(outFileName, output);
};

void ExecDecodeCBC(std::string keyFileName, std::string inFileName, std::string outFileName)
{
	AC::AES::Key<KEY_LEN> key = ReadKeyFile(keyFileName);
	AC::AES::IV iv;
	AC::BlockData<BLOCK_LEN> input;
	AC::BlockData<BLOCK_LEN> output;

	input = ReadBinaryFile(inFileName);

	output = DecodeCBC(key, iv, input);
	WriteBinaryFile(outFileName, output);
};

void ExecEncodeOFB(std::string keyFileName, std::string inFileName, std::string outFileName)
{
	AC::AES::Key<KEY_LEN> key = ReadKeyFile(keyFileName);
	AC::AES::IV iv(GenerateBlock());
	AC::BlockData<BLOCK_LEN> input;
	AC::BlockData<BLOCK_LEN> output;

	input = ReadBinaryFile(inFileName);

	output = EncodeOFB(key, iv, input);
	WriteBinaryFile(outFileName, iv);
	AppendBinaryFile(outFileName, output);
};


void ExecDecodeOFB(std::string keyFileName, std::string inFileName, std::string outFileName)
{
	AC::AES::Key<KEY_LEN> key = ReadKeyFile(keyFileName);
	AC::AES::IV iv;
	AC::BlockData<BLOCK_LEN> input;
	AC::BlockData<BLOCK_LEN> output;

	input = ReadBinaryFile(inFileName);
	iv = input[0];
	input.Delete(0);

	output = DecodeOFB(key, iv, input);
	WriteBinaryFile(outFileName, output);
};

